<template>
	<view class="page">
		<view class="disalog-box" v-if="dialogType">
			<view class="disalog">
				<view class="disalog-title">
					蓝牙搜索到设备
				</view>
				<image class="close-icon" src="/static/image/close_icon.png" mode="aspectFit" @click="disalogClose">
				</image>
				<view class="loading" v-if="printList.length == 0">
					蓝牙设备搜索中...请稍候...
				</view>
				<scroll-view class="scroll-content" scroll-y>
					<view class="disalog-item" v-for="(item,index) in printList" :key="index"
						@click="selectedChange(index)">
						<view class="left-box">
							<image class="icon" src="/static/image/bluetooth_icon.png" mode="aspectFit"></image>
							<view class="device-name">
								{{item.name == '' ? '未知设备': item.name}}
							</view>

						</view>
						<view class="right-box">
							<image class="radio-icon" src="/static/image/radio_icon.png" v-if="index != deviceSelected"
								mode="aspectFit"></image>
							<image class="radio-icon" src="/static/image/radio_selected_icon.png"
								v-if="index == deviceSelected" mode="aspectFit"></image>
						</view>
					</view>
				</scroll-view>
				<view class="button" @click="connectDevice" v-if="printList.length > 0">
					确认
				</view>
			</view>
		</view>
		<view class="disalog-box" v-if="disalogcountType">
			<view class="disalog">
				<view class="disalog-title">
					打印张数
				</view>
				<image class="close-icon" src="/static/image/close_icon.png" mode="aspectFit" @click="printcountClose">
				</image>
				<input class="inputCount" @input="printCountChange" :value="printNum" type="number" />
				<view class="button" @click="printcountConfirm">
					确认
				</view>
			</view>
		</view>
		<view class="print-button" :style="{'backgroundColor': backgroundColor}" @click="printcountOpen">
			{{buttonName}}
		</view>
	</view>
</template>

<script>
	const services_uuid1 = "0000EEE0-0000-1000-8000-00805F9B34FB";
	const services_uuid2 = "0000FF00-0000-1000-8000-00805F9B34FB";
	const services_uuid3 = "49535343-FE7D-4AE5-8FA9-9FAFD205E455";
	const ToBase64 = require('@/utils/base64gb2312.js');
	const Print = require('@/utils/printData.js');
	import {
		ab2hex
	} from '@/utils/utils.js';
	export default {
		props: {
			buttonName: { // 按钮名称
				type: String,
				default: '打印'
			},
			backgroundColor: { // 按钮背景颜色
				type: String,
				default: '#55c69b'
			},
			printInfo: { // 根据printdata中对应函数进行传参
				type: Array,
				default: []
			},
			printStatus: { // 打印类型（可查看下方printTypeList中的name）
				type: String,
				default: ''
			},
		},
		data() {
			return {
				printNum: null, // 打印次数
				infoIndex: 0, // 当前打印数据下标值
				deviceSelected: null, // 蓝牙选中项
				deviceInfo: {}, // 蓝牙设备信息
				disalogcountType: false, // 打印张数悬浮窗状态
				dialogType: false, // 蓝牙设备悬浮窗状态
				printList: [], //打印机列表
				storageList: [], // 缓存搜索数据设备列表
				deviceId: '', // 蓝牙设备id
				writeId: '', // 蓝牙设备写入权限id
				readId: '', // 蓝牙设备读取权限id
				notifyId: '', // 蓝牙设备公告权限id
				printTypeList: [ // 打印功能类型
					{
						name: '批次',
						Command: '',
					}
				],
				sendData64: [],
				characteristicId: '',
				storageDeviceId: '',
				storageServiceId: '',
				storageWriteId: '',
				datapackage: 20,

			}
		},
		mounted() {
			let PrintdeviceId = uni.getStorageSync('PrintdeviceId');
			if (PrintdeviceId) {
				this.deviceId = PrintdeviceId;
			}
		},
		methods: {
			printcountOpen: function() {
				this.disalogcountType = true;
			},
			/**
			 * 打印张数改变触发事件
			 */
			printCountChange: function(e) {
				this.printNum = parseInt(e.detail.value);
			},
			/**
			 * 打印张数关闭触发事件
			 */
			printcountClose: function() {
				this.disalogcountType = false;
				this.printNum = null;
			},
			/**
			 * 打印张数确认触发事件
			 */
			printcountConfirm: function() {
				let printNum = this.printNum;
				if (parseInt(printNum) <= 0) {
					uni.showToast({
						title: '打印次数必须大于0',
						icon: 'none',
						mask: true,
						duration: 2000
					});
					return;
				} else if (printNum == '' || printNum == null) {
					uni.showToast({
						title: '打印次数不能为空',
						icon: 'none',
						mask: true,
						duration: 2000
					});
					return;
				}
				this.disalogcountType = false;
				this.research();
			},
			/**
			 * 选中项改变触发事件
			 */
			selectedChange: function(index) {
				this.deviceSelected = index;
			},
			/**
			 * 悬浮窗关闭触发事件
			 */
			disalogClose: function() {
				this.deviceSelected = null;
				this.dialogType = false;
			},
			//预搜索设备
			research: function() {
				let that = this;
				let printInfo = that.printInfo;
				if (printInfo.length == 0) {
					uni.showToast({
						title: '请选择打印项',
						icon: 'none',
						mask: true,
						duration: 2000
					});
					return;
				}
				uni.closeBluetoothAdapter({
					complete: function(res) {
						that.start();
					}
				})
			},
			/**
			 * 检测是否适合环境
			 */
			start: function() {
			 if (!uni.openBluetoothAdapter) {
					uni.showModal({
						title: '提示',
						content: '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。',
						showCancel: false,
						success: function(res) {}
					});
					return;
				}
				let that = this;
				if (that.printNum == null) {
					that.disalogcountType = true;
				} else {
					that.dialogType = true;
				}
				uni.openBluetoothAdapter({
			  complete: function(res) {
						that.getBluetoothAdapterState();
					}
				})
			},
			/**
			 * 获取蓝牙状态是否开启
			 */
			getBluetoothAdapterState: function() {
				let that = this;
				let deviceId = that.deviceId;
				uni.getBluetoothAdapterState({
			  complete: function(res) {
						if (!!res && res.available) {
							if (deviceId == '') {
								that.startSearch();
							} else {
								that.connectDevice();
							}
						} else {
							that.disalogClose();
							uni.showModal({
								title: '提示',
								content: '请开启手机蓝牙',
								showCancel: false,
								success: function(res) {

								}
							});
						}
					}
				})
			},
			/**
			 * 开始搜索设备
			 */
			startSearch: function() {
				let that = this;
				uni.showLoading({
					title: '搜索中',
					mask: true
			 })
				uni.startBluetoothDevicesDiscovery({
					services: [],
					complete: function(res) {
						setTimeout(function() {
							uni.getBluetoothDevices({
								complete: function(res) {
									uni.hideLoading();
									console.log('devices', res.devices);
									let list = that.filterPrint(res.devices);
									console.log('list', list);
									that.printList = list;
									if (list.length == 0) {
										that.disalogClose();
										uni.showModal({
											title: '提示',
											content: '没有发现新的设备或该机型暂不支持',
											showCancel: false,
											success: function(res) {}
										});
									}
								}
							});
							uni.stopBluetoothDevicesDiscovery({
								success: function(res) {},
							})
						}, 4000)
					}
				})
			},
			/**
			 * 格式化汉印打印机名称列表
			 */
			filterPrint: function(list) {
				var _this = this;
			 let printList = [];
				let storageList = _this.storageList;
				for (let i = 0; i < list.length; i++) {
					let base64 = uni.arrayBufferToBase64(list[i].advertisData);
					let str = Array.prototype.map.call(new Uint8Array(list[i].advertisData), x => ('00' + x.toString(
						16)).slice(-2)).join('');
					if (str.length == 16) {
						let has = false;
						for (let j = 0; j < storageList.length; j++) {
							if (storageList[j].deviceId == list[i].deviceId) {
								has = true;
			 				break;
							}
						}
						if (!has) {
							list[i].address = str.toUpperCase()
							printList.push(list[i]);
						}
					}
				}
				return printList;
			},
			/**
			 * 连接汉印打印机
			 */
			connectDevice: function() {
				let that = this;
				let index = that.deviceSelected;
				let printList = that.printList;
			 let deviceId = that.deviceId;
				if (deviceId == '') {
					deviceId = printList[index].deviceId;
				}
				that.dialogType = false;
				if (index == null && (!deviceId || deviceId == '')) {
					uni.showToast({
						title: '请选择连接设备',
						icon: 'none',
				 	duration: 2000
					});
				 return;
				}
				uni.showLoading({
					title: '连接中...',
					mask: true
				})
				console.log(deviceId);
				uni.createBLEConnection({
					deviceId: deviceId,
					success(res) {
						uni.hideLoading();
						uni.setStorageSync('PrintdeviceId', deviceId);
						that.deviceId = deviceId;
						that.printList = [];
						that.getDeviceService(deviceId);
						uni.showToast({
							title: '连接成功',
							mask: true,
				  	duration: 2000,
							complete() {
								setTimeout(function() {
									that.print(that.infoIndex);
								}, 2000)
							},
				  });
					},
					fail(res) {
						uni.hideLoading();
						uni.showModal({
							title: '提示',
							content: '连接失败,请重试！',
							showCancel: false,
				 		success: function(res) {
								uni.removeStorageSync('PrintdeviceId');
							}
						});
			  }
				})
			},
			/**
			 * 获取蓝牙设备所有服务
			 */
			getDeviceService: function(deviceId) {
				let that = this;
				var deviceId = that.deviceId
				var p = new Promise(function(resolve, reject) {
					uni.getBLEDeviceServices({
						deviceId: deviceId,
						success: function(res) {
							var serviceId = that.filterService(res.services);
							if (serviceId != "") {
								that.serviceId = serviceId;
			  		} else {
								that.closeBLEConnection(deviceId);
								reject('没有找到主服务')
							}
							resolve(serviceId)
						},
			 		fail: function(res) {
							console.log(res)
							that.closeBLEConnection(deviceId);
			 			reject("搜索设备服务失败")
						}
					})
				}).then(function(data) {
					uni.getBLEDeviceCharacteristics({
						deviceId: deviceId,
						serviceId: data,
			  	success: function(res) {
							that.filterCharacter(res.characteristics);
							let writeId = that.writeId;

							if (writeId == '') {
								that.closeBLEConnection(deviceId);
								reject("获取特征值失败")
							}
						},
						fail: function(res) {
							that.closeBLEConnection(deviceId);
							reject("获取特征值失败")
						}
					})
				}).catch(function(error) {
					uni.showModal({
						title: '提示',
						content: error,
						showCancel: false,
						success: function(res) {}
					});
				})
			},
			/**
			 * 格式化蓝牙服务id
			 */
			filterService: function(services, deviceId) {
				let serviceId = "";
				let that = this;
				for (let i = 0; i < services.length; i++) {
					let serverid = services[i].uuid.toUpperCase();
					if (serverid.indexOf(services_uuid1) != -1 ||
						serverid.indexOf(services_uuid2) != -1 ||
						serverid.indexOf(services_uuid3) != -1
					) {
						serviceId = services[i].uuid;
						break;
					}
			 }
				return serviceId;
			},
			/**
			 * 获取当前连接蓝牙设备工作状态
			 */
			filterCharacter: function(characteristics) {
				var that = this;
				var deviceId = that.deviceId;
			 var serviceId = that.serviceId;

				let writeId = '';
				let readId = '';
				let notifyId = '';
				for (let i = 0; i < characteristics.length; i++) {
					let charc = characteristics[i];
					if (charc.properties.write) {
						writeId = charc.uuid;
					}
					if (charc.properties.read) {
						readId = charc.uuid;
					}
					if (charc.properties.notify) {
						notifyId = charc.uuid;
					}

					if (charc.properties.notify || charc.properties.indicate) {
						uni.notifyBLECharacteristicValueChange({
							deviceId,
							serviceId,
							characteristicId: charc.uuid,
							state: true,
						})
					}
				}
				that.writeId = writeId;
				that.readId = readId;
				that.notifyId = notifyId;
				// 操作之前先监听，保证第一时间获取数据
				uni.onBLECharacteristicValueChange((characteristic) => {
					var data = ab2hex(characteristic.value)
					//00: 打印成功
					//01:缺纸
					//02:开盖
					console.log('返回：' + data)
				})
			},
			/**
			 * 打印类型判断
			 */
			print: function(infoIndex) {
				let that = this;
				let deviceId = that.deviceId;
				let printInfo = that.printInfo;
				let serviceId = that.serviceId;
				let writeId = that.writeId;
			 let readId = that.readId;
				let printTypeList = that.printTypeList;
				let printStatus = that.printStatus;
				let index = printTypeList.filter(res => {
				 return res.name == printStatus;
			 })
				if (index.length == 0) {
					uni.showModal({
						title: '提示',
						content: '缺少该指令模板',
						showCancel: false,
						success: function(res) {}
					});
					return false;
				}
				let data = '';
				if (index[0].name == '批次') {
					let params = {
						qrurl: 'https://xwlzz.cn/qr?t=BATCH&id=' + printInfo[infoIndex].id,
						materialName: printInfo[infoIndex].shortName,
						batchNo: printInfo[infoIndex].batchNo,
						MaterialNo: printInfo[infoIndex].materialNo,
						remarkone: printInfo[infoIndex].inputRemark,
						remarktwo: printInfo[infoIndex].inputTwoRemark
					};
					data = Print.batch130(params);
				}
				that.cutCommand(data);
			},
			/**
			 * 向蓝牙设备发送指令
			 */
			cutCommand: function(data) {
				var _this = this;
				var deviceId = _this.deviceId;
				var serviceId = _this.serviceId;
				var writeId = _this.writeId;
				var readId = _this.readId;
				var sendData64 = [];

				var packageLength = _this.datapackage;

				// var packageLength = 10
				// if (_this.data.platform == 'ios')
				//   packageLength = 30
				var byData = uni.base64ToArrayBuffer(ToBase64.encode64gb2312(data))
				console.log(Math.ceil(byData.byteLength / packageLength));
				for (let i = 0; i < Math.ceil(byData.byteLength / packageLength); i++) {
					console.log("3")

					var ble_end = packageLength * (i + 1);
					var ble_begin = i * packageLength

					if (ble_end > byData.byteLength) {
						//从begin（包括），到end（不包括）。
						const newBuffer = byData.slice(ble_begin); // 从哪个开始到那个结束
						sendData64[i] = newBuffer
					} else {
						const newBuffer = byData.slice(ble_begin, ble_end); // 从哪个开始到那个结束
						sendData64[i] = newBuffer
					}
				}
				this.sendData64 = sendData64;
				var p = new Promise(function(resolve, reject) {
					_this.writeBLECharacteristicValue(deviceId, serviceId, writeId, 1); //32s
					resolve('ok')
				}).then(function(data) {}).catch(function(error) {
					console.log('error:' + error)
					uni.showModal({
						title: '',
						content: error,
						showCancel: false,
						success: function(res) {}
					});
				})
			},
			//向低功耗蓝牙设备特征值中写入二进制数据
			writeBLECharacteristicValue: function(deviceId, serviceId, writeId, times) {
				var that = this;
				let printInfo = that.printInfo;
				var sendData64 = that.sendData64;
			 if (sendData64.length >= times) {
			 	uni.writeBLECharacteristicValue({
						deviceId: deviceId,
						serviceId: serviceId,
						characteristicId: writeId,
						value: sendData64[times - 1],
						success: function(res) {
							uni.showLoading({
								title: '传输中...',
								mask: true
							});
							that.writeBLECharacteristicValue(deviceId, serviceId, writeId, ++times);
						},
						fail: function(res) {
							console.log(res);
							console.log('deviceId:' + deviceId);
							console.log('serviceId:' + serviceId);
							console.log('writeId:' + writeId);
							uni.showModal({
								title: '提示',
								content: '传输失败',
								showCancel: false,
								success: function(res) {}
							});
						}
					})

				} else {
					console.log("======数据完成 =======")
					uni.hideLoading();
					let printNum = that.printNum;
					let infoIndex = that.infoIndex;
					if (printNum <= 0) {
						that.printNum = null;
						uni.showModal({
							title: '提示',
							content: '打印完成',
							showCancel: false,
							success: function(res) {
								that.closeBLEConnection(deviceId);
								that.infoIndex = 0;
							}
						});
					}else if(printNum > 0){
						console.log('printNum',printNum);
						if (infoIndex < printInfo.length - 1) {
							infoIndex += 1;
							that.infoIndex = infoIndex;
							console.log('infoIndex',infoIndex);
							that.print(infoIndex);
						} else {
								printNum = printNum - 1;
								that.printNum = printNum;
								if(printNum > 0){
									infoIndex = 0;
									that.infoIndex = infoIndex;
									console.log('infoIndex',infoIndex);
									that.print(infoIndex);
								}
						}
					}
					var readId = that.readId;
					uni.readBLECharacteristicValue({
			  	deviceId,
						serviceId,
						characteristicId: readId,
						success(res) {
							console.log('readBLECharacteristicValue:', res)
						}
					})
				}
			},
			/**
			 * 断开蓝牙连接
			 */
			closeBLEConnection: function(deviceId) {
				uni.closeBLEConnection({
					deviceId: deviceId,
					success: function(res) {}
				})
			},
		}
	}
</script>

<style lang="scss" scoped>
	.page {
		width: 100%;
		height: 100%;
	}

	.disalog-box {
		width: 100%;
		height: 100vh;
		position: fixed;
		background-color: rgba(0, 0, 0, 0.5);
		left: 0;
		top: 0;

		.disalog {
			background-color: white;
			border-radius: 10rpx;
			position: absolute;
			top: 50%;
			left: 50%;
			animation-name: disalogshow;
			animation-duration: 1s;
			width: calc(100% - 80rpx);
			transform: translate(-50%, -50%);
			box-sizing: border-box;
			padding: 20rpx;

			.disalog-title {
				text-align: center;
				margin-bottom: 20rpx;
			}

			.loading {
				text-align: center;
				font-size: 28rpx;
			}

			.close-icon {
				width: 50rpx;
				height: 50rpx;
				position: absolute;
				right: 35rpx;
				top: 15rpx;
			}

			.inputCount {
				height: 70rpx;
				line-height: 70rpx;
				font-size: 28rpx;
				border: 1px solid #d7d7d7;
				border-radius: 10rpx;
				padding: 0 10rpx;
				box-sizing: border-box;
				text-align: center;
			}

			.disalog-item {
				line-height: 80rpx;
				height: 80rpx;
				font-size: 28rpx;
				border-top: 1px solid #d0f0fd;
				border-bottom: 1px solid #d0f0fd;
				display: flex;
				justify-content: space-between;

				.left-box {
					display: flex;

					.icon {
						width: 50rpx;
						height: 50rpx;
						margin: 15rpx;
					}
				}

				.right-box {
					.radio-icon {
						margin: 15rpx;
						width: 50rpx;
						height: 50rpx;
					}
				}
			}

			.button {
				margin-top: 20rpx;
				width: 100%;
				height: 70rpx;
				line-height: 70rpx;
				text-align: center;
				color: white;
				border-radius: 10rpx;
				background-color: #1296db;
			}
		}
	}

	.print-button {
		width: calc(100% - 20rpx);
		white-space: nowrap;
		height: 100%;
		border-radius: 10rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		text-align: center;
		color: white;
		padding: 0 10rpx;
		font-size: 28rpx;
	}

	.scroll-content {
		height: 30vh;
	}

	@keyframes disalogshow {
		0% {
			transform: translate(-50%, -60%);
			// transform: scale(0);
			opacity: 0;
		}

		100% {
			transform: translate(-50%, -50%);
			// transform: scale(1);
			opacity: 1;
		}
	}
</style>
